<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><link rel="stylesheet" type="text/css" href="style.css" /><script type="text/javascript" src="highlight.js"></script></head><body><pre><span class="hs-pragma">{-# LANGUAGE CPP #-}</span><span>
</span><span id="line-2"></span><span class="hs-comment">{- |
Module      :  Control.Monad.Except
Copyright   :  (c) Michael Weber &lt;michael.weber@post.rwth-aachen.de&gt; 2001,
               (c) Jeff Newbern 2003-2006,
               (c) Andriy Palamarchuk 2006
License     :  BSD-style (see the file LICENSE)

Maintainer  :  libraries@haskell.org
Stability   :  experimental
Portability :  non-portable (multi-parameter type classes)

[Computation type:] Computations which may fail or throw exceptions.

[Binding strategy:] Failure records information about the cause\/location
of the failure. Failure values bypass the bound function,
other values are used as inputs to the bound function.

[Useful for:] Building computations from sequences of functions that may fail
or using exception handling to structure error handling.

[Example type:] @'Either' String a@

The Error monad (also called the Exception monad).

@since 2.2.1
-}</span><span>
</span><span id="line-28"></span><span>
</span><span id="line-29"></span><span class="hs-comment">{-
  Rendered by Michael Weber &lt;mailto:michael.weber@post.rwth-aachen.de&gt;,
  inspired by the Haskell Monad Template Library from
    Andy Gill (&lt;http://web.cecs.pdx.edu/~andy/&gt;)
-}</span><span>
</span><span id="line-34"></span><span class="hs-keyword">module</span><span> </span><span class="hs-identifier">Control.Monad.Except</span><span>
</span><span id="line-35"></span><span>  </span><span class="hs-special">(</span><span>
</span><span id="line-36"></span><span>    </span><span class="annot"><span class="hs-comment">-- * Warning</span></span><span>
</span><span id="line-37"></span><span>    </span><span class="hs-comment">-- $warning</span><span>
</span><span id="line-38"></span><span>    </span><span class="hs-comment">-- * Monads with error handling</span><span>
</span><span id="line-39"></span><span>    </span><span class="annot"><a href="Control.Monad.Error.Class.html#MonadError"><span class="hs-identifier">MonadError</span></a></span><span class="hs-special">(</span><span class="hs-glyph">..</span><span class="hs-special">)</span><span class="hs-special">,</span><span>
</span><span id="line-40"></span><span>    </span><span class="annot"><a href="Control.Monad.Error.Class.html#liftEither"><span class="hs-identifier">liftEither</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-41"></span><span>    </span><span class="annot"><span class="hs-comment">-- * The ExceptT monad transformer</span></span><span>
</span><span id="line-42"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#ExceptT"><span class="hs-identifier">ExceptT</span></a></span><span class="hs-special">(</span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#ExceptT"><span class="hs-identifier">ExceptT</span></a></span><span class="hs-special">)</span><span class="hs-special">,</span><span>
</span><span id="line-43"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#Except"><span class="hs-identifier">Except</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-44"></span><span>
</span><span id="line-45"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#runExceptT"><span class="hs-identifier">runExceptT</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-46"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#mapExceptT"><span class="hs-identifier">mapExceptT</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-47"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#withExceptT"><span class="hs-identifier">withExceptT</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-48"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#runExcept"><span class="hs-identifier">runExcept</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-49"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#mapExcept"><span class="hs-identifier">mapExcept</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-50"></span><span>    </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#withExcept"><span class="hs-identifier">withExcept</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-51"></span><span>
</span><span id="line-52"></span><span>    </span><span class="hs-keyword">module</span><span> </span><span class="annot"><a href="../../base/src/Control.Monad.html#"><span class="hs-identifier">Control.Monad</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-53"></span><span>    </span><span class="hs-keyword">module</span><span> </span><span class="annot"><a href="../../base/src/Control.Monad.Fix.html#"><span class="hs-identifier">Control.Monad.Fix</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-54"></span><span>    </span><span class="hs-keyword">module</span><span> </span><span class="annot"><a href="Control.Monad.Trans.html"><span class="hs-identifier">Control.Monad.Trans</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-55"></span><span>    </span><span class="annot"><span class="hs-comment">-- * Example 1: Custom Error Data Type</span></span><span>
</span><span id="line-56"></span><span>    </span><span class="annot"><span class="hs-comment">-- $customErrorExample</span></span><span>
</span><span id="line-57"></span><span>
</span><span id="line-58"></span><span>    </span><span class="annot"><span class="hs-comment">-- * Example 2: Using ExceptT Monad Transformer</span></span><span>
</span><span id="line-59"></span><span>    </span><span class="annot"><span class="hs-comment">-- $ExceptTExample</span></span><span>
</span><span id="line-60"></span><span>  </span><span class="hs-special">)</span><span> </span><span class="hs-keyword">where</span><span>
</span><span id="line-61"></span><span>
</span><span id="line-62"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="Control.Monad.Error.Class.html"><span class="hs-identifier">Control.Monad.Error.Class</span></a></span><span>
</span><span id="line-63"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="Control.Monad.Trans.html"><span class="hs-identifier">Control.Monad.Trans</span></a></span><span>
</span><span id="line-64"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#"><span class="hs-identifier">Control.Monad.Trans.Except</span></a></span><span>
</span><span id="line-65"></span><span>  </span><span class="hs-special">(</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#ExceptT"><span class="hs-identifier">ExceptT</span></a></span><span class="hs-special">(</span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#ExceptT"><span class="hs-identifier">ExceptT</span></a></span><span class="hs-special">)</span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#Except"><span class="hs-identifier">Except</span></a></span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#except"><span class="hs-identifier">except</span></a></span><span>
</span><span id="line-66"></span><span>  </span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#runExcept"><span class="hs-identifier">runExcept</span></a></span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#runExceptT"><span class="hs-identifier">runExceptT</span></a></span><span>
</span><span id="line-67"></span><span>  </span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#mapExcept"><span class="hs-identifier">mapExcept</span></a></span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#mapExceptT"><span class="hs-identifier">mapExceptT</span></a></span><span>
</span><span id="line-68"></span><span>  </span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#withExcept"><span class="hs-identifier">withExcept</span></a></span><span class="hs-special">,</span><span> </span><span class="annot"><a href="../../transformers/src/Control.Monad.Trans.Except.html#withExceptT"><span class="hs-identifier">withExceptT</span></a></span><span>
</span><span id="line-69"></span><span>  </span><span class="hs-special">)</span><span>
</span><span id="line-70"></span><span>
</span><span id="line-71"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="../../base/src/Control.Monad.html#"><span class="hs-identifier">Control.Monad</span></a></span><span>
</span><span id="line-72"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="../../base/src/Control.Monad.Fix.html#"><span class="hs-identifier">Control.Monad.Fix</span></a></span><span class="hs-cpp">

#if defined(__GLASGOW_HASKELL__) &amp;&amp; __GLASGOW_HASKELL__ &lt; 707
</span><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control.Monad.Instances</span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span><span class="hs-cpp">
#endif
</span><span>
</span><span id="line-78"></span><span class="hs-comment">{- $warning
Please do not confuse 'ExceptT' and 'throwError' with 'Control.Exception.Exception' /
'Control.Exception.SomeException' and 'Control.Exception.catch', respectively. The latter
are for exceptions built into GHC, by default, and are mostly used from within the IO monad.
They do not interact with the \&quot;exceptions\&quot; in this package at all. This package allows you
to define a new kind of exception control mechanism which does not necessarily need your code to
be placed in the IO monad.

In short, all \&quot;catching\&quot; mechanisms in this library will be unable to catch exceptions thrown
by functions in the &quot;Control.Exception&quot; module, and vice-versa.
-}</span><span>
</span><span id="line-89"></span><span>
</span><span id="line-90"></span><span class="hs-comment">{- $customErrorExample
Here is an example that demonstrates the use of a custom error data type with
the 'throwError' and 'catchError' exception mechanism from 'MonadError'.
The example throws an exception if the user enters an empty string
or a string longer than 5 characters. Otherwise it prints length of the string.

&gt;-- This is the type to represent length calculation error.
&gt;data LengthError = EmptyString  -- Entered string was empty.
&gt;          | StringTooLong Int   -- A string is longer than 5 characters.
&gt;                                -- Records a length of the string.
&gt;          | OtherError String   -- Other error, stores the problem description.
&gt;
&gt;-- Converts LengthError to a readable message.
&gt;instance Show LengthError where
&gt;  show EmptyString = &quot;The string was empty!&quot;
&gt;  show (StringTooLong len) =
&gt;      &quot;The length of the string (&quot; ++ (show len) ++ &quot;) is bigger than 5!&quot;
&gt;  show (OtherError msg) = msg
&gt;
&gt;-- For our monad type constructor, we use Either LengthError
&gt;-- which represents failure using Left LengthError
&gt;-- or a successful result of type a using Right a.
&gt;type LengthMonad = Either LengthError
&gt;
&gt;main = do
&gt;  putStrLn &quot;Please enter a string:&quot;
&gt;  s &lt;- getLine
&gt;  reportResult (calculateLength s)
&gt;
&gt;-- Attempts to calculate length and throws an error if the provided string is
&gt;-- empty or longer than 5 characters.
&gt;-- (Throwing an error in this monad means returning a 'Left'.)
&gt;calculateLength :: String -&gt; LengthMonad Int
&gt;calculateLength [] = throwError EmptyString
&gt;calculateLength s | len &gt; 5 = throwError (StringTooLong len)
&gt;                  | otherwise = return len
&gt;  where len = length s
&gt;
&gt;-- Prints result of the string length calculation.
&gt;reportResult :: LengthMonad Int -&gt; IO ()
&gt;reportResult (Right len) = putStrLn (&quot;The length of the string is &quot; ++ (show len))
&gt;reportResult (Left e) = putStrLn (&quot;Length calculation failed with error: &quot; ++ (show e))
-}</span><span>
</span><span id="line-133"></span><span>
</span><span id="line-134"></span><span class="hs-comment">{- $ExceptTExample
@'ExceptT'@ monad transformer can be used to add error handling to another monad.
Here is an example how to combine it with an @IO@ monad:

&gt;import Control.Monad.Except
&gt;
&gt;-- An IO monad which can return String failure.
&gt;-- It is convenient to define the monad type of the combined monad,
&gt;-- especially if we combine more monad transformers.
&gt;type LengthMonad = ExceptT String IO
&gt;
&gt;main = do
&gt;  -- runExceptT removes the ExceptT wrapper
&gt;  r &lt;- runExceptT calculateLength
&gt;  reportResult r
&gt;
&gt;-- Asks user for a non-empty string and returns its length.
&gt;-- Throws an error if user enters an empty string.
&gt;calculateLength :: LengthMonad Int
&gt;calculateLength = do
&gt;  -- all the IO operations have to be lifted to the IO monad in the monad stack
&gt;  liftIO $ putStrLn &quot;Please enter a non-empty string: &quot;
&gt;  s &lt;- liftIO getLine
&gt;  if null s
&gt;    then throwError &quot;The string was empty!&quot;
&gt;    else return $ length s
&gt;
&gt;-- Prints result of the string length calculation.
&gt;reportResult :: Either String Int -&gt; IO ()
&gt;reportResult (Right len) = putStrLn (&quot;The length of the string is &quot; ++ (show len))
&gt;reportResult (Left e) = putStrLn (&quot;Length calculation failed with error: &quot; ++ (show e))
-}</span><span>
</span><span id="line-166"></span></pre></body></html>